#! /usr/bin/env python
# -*- coding: utf-8 -*-
# vim:fenc=utf-8
#
# Copyright © 2018 crane <crane@crane-pc>

from matrix_tools import *
from linear_tools import *
from dot_cross_product import dot_product


''' 所有的公式都由如下导出:
    b 为被投影向量, a为投影目的向量. (投影向量于投影目的向量成比例关系)

    b投影到a上后, 为a的x倍(即x * a)
    : (b - x*a) ⊥ a (b-x*a)为b投影到a过程中的垂直分量

        1: (b - x * a) * aT == 0 (即(b-x*a) 点乘a 等于0)
    ====2:> b * aT == x*a*aT      (基础等式)
    ====3:> x = b * aT / a * aT   (投影是a的倍数)
    ====4:> x*a = (b*aT / a*aT)*a (xa是投影向量)

    注意这里a和b为行向量, 如果为列向量, 左右顺序要反.
'''


class TwoDProject:
    def __init__(self, v):
        self.v = v
        self.proj_m = self.proj_matrix()

    def proj_matrix(self):
        ''' 将向量投影到v, 求投影矩阵
            这里的v约定是行向量[a1, b1] ---> (如果是列向量, 则计算顺序要改变)
        '''
        a = [self.v]
        at = transpose_matrix(a)

        m  = multiply(at, a)
        co = multiply(a, at)[0][0]

        return scale_matrix(m, 1/co)

    def proj(self, v):
        # method 1: 用投影矩阵
        # return multiply([v], self.proj_m)[0]

        # method 2: 用投影比例
        # co = dot_product(v, self.v) / dot_product(self.v, self.v)
        co = self.multiple_proj(v)
        return scale_vector(self.v, co)

    def multiple_proj(self, v):
        ''' v投影到self.v上, 是self.v 多少倍
            等于 b * aT / a * aT
        '''
        return dot_product(v, self.v) / dot_product(self.v, self.v)


def test():
    t = TwoDProject([1, 2])
    proj_m = t.proj_m
    show_matrix(proj_m, 'proj')

    v = [1, 3]
    p1 = t.proj(v)
    print(p1)

    print(t.multiple_proj(v))


def main():
    print("start main")
    test()

if __name__ == "__main__":
    main()
